/*Kood PostgreSQL (ver 17) jaoks.
Iga amet on seotud null vi rohkem ttajaga.
Iga ttaja ttab tpselt hes ametis.*/

createdb tootajad
/*Andmebaasi loomine.

Alternatiivina serveris andmebaasi loomisele saaks seda koodi prooviks kivitada siin:
https://www.db-fiddle.com/
vi siin:
https://sqlfiddle.com/postgresql/online-compiler
*/

CREATE TABLE Amet (amet_kood SMALLINT NOT NULL,
nimetus VARCHAR(100) NOT NULL,
palk DECIMAL(10,2) NOT NULL,
CONSTRAINT pk_amet PRIMARY KEY (amet_kood),
CONSTRAINT ak_amet_nimetus UNIQUE (nimetus),
CONSTRAINT chk_amet_palk CHECK (palk>0));
/*Luuakse baastabel e tabel. See on nimega tabel, mis EI OLE defineeritud teiste 
tabelite phjal. Tabeli loomisel deklareeritakse piirangud e kitsendused andmetele
ja andmeid kontrollitakse nende kitsenduste vastu kohe kirjutamisel - andmemuudatused,
mis ritavad andmebaasi lisada kitsendustele mittevastavaid andmeid, ebannestuvad.*/

INSERT INTO Amet (amet_kood, nimetus, palk) 
VALUES (1, 'Juhataja', 3000), (2, 'Raamatupidaja', 2800), (3, 'Koristaja', 2000);
/*Korraga saab tabelisse lisada mitu rida.*/

INSERT INTO Amet (amet_kood, nimetus, palk) 
VALUES (300000, 'IT-administraator', 1500);
/*Ebannestub, sest vrtus 300000 ei kuulu tpi SMALLINT.*/

INSERT INTO Amet (amet_kood, nimetus, palk) 
VALUES (3, 'IT-administraator', 2500);
/*Ebannestub, sest selline amet_kood on juba registreeritud.*/

INSERT INTO Amet (amet_kood, nimetus, palk) 
VALUES (4, 'Koristaja', 2500);
/*Ebannestub, sest sellise nimetusega amet on juba registreeritud.*/

INSERT INTO Amet (amet_kood, nimetus) 
VALUES (4, 'IT-administraator');
/*Ebannestub, sest palk puudub.*/

INSERT INTO Amet (amet_kood, nimetus, palk) 
VALUES (4, 'IT-administraator', -5);
/*Ebannestub, sest palk on negatiivne.*/

CREATE TABLE Tootaja (tootaja_id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY,
e_meil VARCHAR(254) NOT NULL,
eesnimi VARCHAR(50),
perenimi VARCHAR (50),
amet_kood SMALLINT NOT NULL DEFAULT 2,
CONSTRAINT pk_tootaja PRIMARY KEY (tootaja_id),
CONSTRAINT chk_tootaja_eesnimi_perenimi CHECK (eesnimi IS NOT NULL OR perenimi IS NOT NULL),
CONSTRAINT chk_tootaja_e_meil CHECK (e_meil LIKE '%@%'),
CONSTRAINT fk_tootaja_amet FOREIGN KEY (amet_kood) 
REFERENCES Amet(amet_kood) ON UPDATE CASCADE);

/*
Nimed vivad olla pikad: https://en.wikipedia.org/wiki/Hubert_Blaine_Wolfeschlegelsteinhausenbergerdorff_Sr.
Nime osad vivad puududa: https://digikogu.taltech.ee/et/Item/ab7e8f7e-ce28-4cc1-bb78-40c624d19bf6
Meiliaadress vib olla kuni 254 mrki: https://blog.moonmail.io/what-is-the-maximum-length-of-a-valid-email-address-f712c6c4bc93
*/

/*Meiliaadress peab olema tstutundetult unikaalne.
Nide, et SQL-andmebaasissteemid vivad pakkuda vimalusi, mida 
SQL standard ette ei ne.*/
ALTER TABLE Tootaja ADD CONSTRAINT
ak_tootaja_e_meil EXCLUDE
(Upper(e_meil) WITH =);

INSERT INTO Tootaja (e_meil, eesnimi, perenimi, amet_kood)
VALUES ('karl.kask@online.ee','Karl','Kask',1),
('karin.kadakas@mail.ee','Karin','Kadakas',2),
('liis.lehis@mail.ee','Liis','Lehis',2)
RETURNING tootaja_id, e_meil;
/*Lasen tagastada genereeritud identifikaatorid.*/

INSERT INTO Tootaja (e_meil, eesnimi, perenimi, amet_kood)
VALUES ('Karl.Kask@online.ee','Karl','Kask',1);
/*Lisamine ebannestub, sest tstundetult vaadates on selline meiliaadress juba registreeritud.*/

INSERT INTO Tootaja (e_meil, eesnimi, perenimi, amet_kood)
VALUES ('toomas.tuisk@hot.ee','Toomas','Tuisk',100);
/*Lisamine ebannestub, sest sellise koodiga ametit pole registreeritud.
Andmebaasissteem kontrollib viidete terviklikkuse reeglit - referential integrity rule.*/

UPDATE Amet SET amet_kood=100 WHERE amet_kood=1;
/*Muudatus nnestub, muudetakse ameti koode ka tabelis Tootaja.*/

SELECT * FROM Tootaja;

DELETE FROM Amet WHERE amet_kood=2;
/*Kustutamine ebannestub, sest sellise koodiga ametis ttab vhemalt ks ttaja.*/

DELETE FROM Amet WHERE amet_kood=4;
/*Kustutamine nnestub, sest sellise koodiga ametis ei tta htegi ttajat.*/

SELECT *
FROM Tootaja 
WHERE perenimi LIKE 'K%';

WITH tootajad_k AS (SELECT *
FROM Tootaja 
WHERE perenimi LIKE 'K%')
SELECT Count(*) AS arv
FROM tootajad_k;

/*SQL defineerib hulga lugemisoperaatoreid, mis vimaldavad olemasolevate tabelite phjal tuletada uusi tabeleid.
Olemasolevatest faktidest tuletatakse uusi.
Iga sellise operatsiooni sisendiks on ks vi mitu tabelit ning tulemuseks samuti tabel, 
mis vib omakorda olla sisendiks jrgnevale operatsioonile.
Eelnevad SELECT laused annavad tulemuseks NIMETU tabeli -
vastandina NIMEGA tabelile, mis tekib niteks CREATE TABLE lause tulemusena.
*/

START TRANSACTION;
DELETE FROM Tootaja;
DELETE FROM Amet;
SELECT * FROM Tootaja;
SELECT * FROM Amet;
ROLLBACK;
SELECT * FROM Tootaja;
/*Andmebaasikeele lauseid saab koondada hte loogilisse tervikusse e transaktsiooni
e tehingusse. Thendab, et need laused tidetakse kas kik vi
jetakse kik titmata.*/

SELECT amet_kood, nimetus AS amet_nimetus, palk, e_meil, eesnimi, perenimi
FROM Tootaja INNER JOIN Amet USING (amet_kood)
ORDER BY amet_kood, e_meil;
/*Leia ttajate ja nende ametite andmed.*/

SELECT amet_kood, nimetus
FROM Amet
WHERE NOT EXISTS (SELECT * 
FROM Tootaja
WHERE Tootaja.amet_kood=Amet.amet_kood);

SELECT amet_kood, nimetus
FROM Amet
WHERE amet_kood NOT IN (SELECT amet_kood
FROM Tootaja);
/*Leia ametid, kus ei tta htki ttajat.
NOT IN pring tidetakse suurte andmehulkade korral PostgreSQLis palju aeglasemalt kui NOT EXISTS pring.
Nide sellest, kuidas "abstraktsioon tilgub lbi" e ssteemi hingeelu probleemid mjutavad
selle kasutamist.*/

ANALYZE;
/*Vrskenda andmebaasi statistikat.*/

EXPLAIN ANALYZE SELECT amet_kood, nimetus
FROM Amet
WHERE amet_kood NOT IN (SELECT amet_kood
FROM Tootaja);
/*SELECT lause on deklaratiivne - eldaks, mida on vaja leida.
Selle alusel koostab andmebaasissteem enda sisestest operatsioonidest (niteks loe indeksit, loe tabeli plokke, eemalda kordused rsivrtuste 
leidmise kaudu) koosneva protseduuri - sammude jada. Seda protseduuri nimetatakse titmisplaaniks.
Andmebaasissteem ritab koostada vimalikult optimaalse titmisplaani.
Selle lausega saab vaadata lause titmise plaani ja titmise aega.*/

CREATE OR REPLACE VIEW tootajateta_amet WITH (security_barrier) AS
SELECT amet_kood, nimetus
FROM Amet
WHERE NOT EXISTS (SELECT * 
FROM Tootaja
WHERE Tootaja.amet_kood=Amet.amet_kood);
/*Luuakse virtuaalne tabel e vaade. See on nimega tabel, mis ON defineeritud teiste 
tabelite phjal (antud juhul Amet ja Tootaja).*/

SELECT *
FROM tootajateta_amet;
/*Vaate phjal saab teha pringuid e SELECT lauseid ning
lbi lihtsamate vaadete ka muuta andmeid baastabelites.*/

DROP TABLE Tootaja CASCADE;
DROP TABLE Amet CASCADE;
/*Tabelite kustutamine.
CASCADE thendab, et kustutatakse ka sltuvad andmebaasiobjektid -
antud juhul vaade.*/

dropdb tootajad
/*Andmebaasi kustutamine.*/